home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / os2 / pccts.zip / BITS.C < prev    next >
C/C++ Source or Header  |  1992-12-08  |  9KB  |  339 lines

  1. /*
  2.  * bits.c -- manage creation and output of bit sets used by the parser.
  3.  *
  4.  * SOFTWARE RIGHTS
  5.  *
  6.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  7.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  8.  * company may do whatever they wish with source code distributed with
  9.  * PCCTS or the code generated by PCCTS, including the incorporation of
  10.  * PCCTS, or its output, into commerical software.
  11.  * 
  12.  * We encourage users to develop software with PCCTS.  However, we do ask
  13.  * that credit is given to us for developing PCCTS.  By "credit",
  14.  * we mean that if you incorporate our source code into one of your
  15.  * programs (commercial product, research project, or otherwise) that you
  16.  * acknowledge this fact somewhere in the documentation, research report,
  17.  * etc...  If you like PCCTS and have developed a nice tool with the
  18.  * output, please mention that you developed it using PCCTS.  In
  19.  * addition, we ask that this header remain intact in our source code.
  20.  * As long as these guidelines are kept, we expect to continue enhancing
  21.  * this system and expect to make other tools available as they are
  22.  * completed.
  23.  *
  24.  * ANTLR 1.06
  25.  * Terence Parr
  26.  * Purdue University
  27.  * 1989-1992
  28.  */
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include "set.h"
  32. #include "syn.h"
  33. #include "hash.h"
  34. #include "generic.h"
  35. #include "dlgdef.h"
  36.  
  37. #define BitsPerByte        8
  38. #define BitsPerWord        BitsPerByte*sizeof(unsigned)
  39.  
  40. static unsigned *setwd = NULL;
  41. int setnum = -1;
  42. int wordnum = 0;
  43.  
  44. int esetnum = 0;
  45.  
  46. /* Create a new setwd (ignoring [Ep] token on end) */
  47. void
  48. NewSetWd()
  49. {
  50.     unsigned *p;
  51.  
  52.     if ( setwd == NULL )
  53.     {
  54.         setwd = (unsigned *) calloc(TokenNum, sizeof(unsigned));
  55.         require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");
  56.     }
  57.     for (p = setwd; p<&(setwd[TokenNum]); p++)  {*p=0;}
  58.     wordnum++;
  59. }
  60.  
  61. /* Dump the current setwd to ErrFile. 0..MaxTokenVal */
  62. void
  63. DumpSetWd()
  64. {
  65.     int i,c=1;
  66.  
  67.     if ( setwd==NULL ) return;
  68.     fprintf(DefFile, "extern unsigned setwd%d[];\n", wordnum);
  69.     fprintf(ErrFile, "unsigned setwd%d[%d] = {", wordnum, TokenNum-1);
  70.     for (i=0; i<TokenNum-1; i++)
  71.     {
  72.         if ( i!=0 ) fprintf(ErrFile, ",");
  73.         if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;
  74.         fprintf(ErrFile, "0x%x", setwd[i]);
  75.     }
  76.     fprintf(ErrFile, "};\n");
  77. }
  78.  
  79. /* Make a new set.  Dump old setwd and create new setwd if current setwd is full */
  80. void
  81. NewSet()
  82. {
  83.     setnum++;
  84.     if ( setnum==BitsPerWord )        /* is current setwd full? */
  85.     {
  86.         DumpSetWd(); NewSetWd(); setnum = 0;
  87.     }
  88. }
  89.  
  90. /* s is a set of tokens.  Turn on bit at each token position in set 'setnum' */
  91. void
  92. FillSet(s)
  93. set s;
  94. {
  95.     unsigned mask=(1<<setnum);
  96.     int e;
  97.  
  98.     while ( !set_nil(s) )
  99.     {
  100.         e = set_int(s);
  101.         set_rm(e, s);
  102.         setwd[e] |= mask;
  103.     }
  104. }
  105.  
  106.                     /* E r r o r  C l a s s  S t u f f */
  107.  
  108. /* compute the FIRST of a rule for the error class stuff */
  109. static set
  110. Efirst(rule, eclass)
  111. char *rule;
  112. ECnode *eclass;
  113. {
  114.     set rk, a;
  115.     Junction *r;
  116.     RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);
  117.  
  118.     if ( q == NULL )
  119.     {
  120.         warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",
  121.                         rule, TokenStr[eclass->tok]));
  122.         return empty;
  123.     }
  124.     r = RulePtr[q->rulenum];
  125.     r->end->halt = TRUE;        /* don't let reach fall off end of rule here */
  126.     rk = empty;
  127.     REACH(r, 1, &rk, a);
  128.     r->end->halt = FALSE;
  129.     return a;
  130. }
  131.  
  132. /*
  133.  * scan the list of tokens/eclasses/nonterminals filling the new eclass
  134.  * with the set described by the list.  Note that an eclass can be
  135.  * quoted to allow spaces etc... However, an eclass must not conflict
  136.  * with a reg expr found elsewhere.  The reg expr will be taken over
  137.  * the eclass name.
  138.  */
  139. static void
  140. doEclass(eclass)
  141. char *eclass;        /* pointer to Error Class */
  142. {
  143.     TermEntry *q;
  144.     ECnode *p;
  145.     ListNode *e;
  146.     int t, deg=0;
  147.     set a;
  148.     require(eclass!=NULL, "doEclass: NULL eset");
  149.     
  150.     p = (ECnode *) eclass;
  151.     lexmode(p->lexclass);    /* switch to lexclass where errclass is defined */
  152.     p->eset = empty;
  153.     for (e = (p->elist)->next; e!=NULL; e=e->next)
  154.     {
  155.         if ( islower( *(e->elem) ) )    /* is it a rule ref? (alias FIRST request) */
  156.         {
  157.             a = Efirst(e->elem, p);
  158.             set_orin(&p->eset, a);
  159.             deg += set_deg(a);
  160.             set_free( a );
  161.             continue;
  162.         }
  163.         else if ( *(e->elem)=='"' )
  164.         {
  165.             t = 0;
  166.             q = (TermEntry *) hash_get(Texpr, e->elem);
  167.             if ( q == NULL )
  168.             {
  169.                 /* if quoted and not an expr look for eclass name */
  170.                 q = (TermEntry *) hash_get(Tname, e->elem=StripQuotes(e->elem));
  171.                 if ( q != NULL ) t = q->token;
  172.             }
  173.             else t = q->token;
  174.         }
  175.         else    /* labelled token/eclass */
  176.         {
  177.             q = (TermEntry *) hash_get(Tname, e->elem);
  178.             if ( q != NULL ) t = q->token; else t=0;
  179.         }
  180.         if ( t!=0 )
  181.         {
  182.             set_orel(t, &p->eset);
  183.             deg++;
  184.         }
  185.         else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",
  186.                             e->elem, TokenStr[p->tok]));
  187.     }
  188.     p->setdeg = deg;
  189. }
  190.  
  191. void
  192. ComputeErrorSets()
  193. {
  194.     list_apply(eclasses, doEclass);
  195. }
  196.  
  197. /* replace a subset of an error set with an error class name if a subset is found
  198.  * repeat process until no replacements made
  199.  */
  200. void
  201. SubstErrorClass(f)
  202. set *f;
  203. {
  204.     int max, done = 0;
  205.     ListNode *p;
  206.     ECnode *ec, *maxclass = NULL;
  207.     set a;
  208.     require(f!=NULL, "SubstErrorClass: NULL eset");
  209.  
  210.     if ( eclasses == NULL ) return;
  211.     while ( !done )
  212.     {
  213.         max = 0;
  214.         maxclass = NULL;
  215.         for (p=eclasses->next; p!=NULL; p=p->next)    /* chk all error classes */
  216.         {
  217.             ec = (ECnode *) p->elem;
  218.             if ( ec->setdeg > max )
  219.             {
  220.                 if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )
  221.                     {maxclass = ec; max=ec->setdeg;}
  222.             }
  223.         }
  224.         if ( maxclass != NULL )    /* if subset found, replace with token */
  225.         {
  226.             a = set_dif(*f, maxclass->eset);
  227.             set_orel(maxclass->tok, &a);
  228.             set_free(*f);
  229.             *f = a;
  230.         }
  231.         else done = 1;
  232.     }
  233. }
  234.  
  235. /* Define a new error set.  WARNING...set-implementation dependent */
  236. int
  237. DefErrSet(f)
  238. set *f;
  239. {
  240.     unsigned *p, *endp;
  241.     int e=1;
  242.     require(!set_nil(*f), "DefErrSet: nil set to dump?");
  243.  
  244.     SubstErrorClass(f);
  245.     p = f->setword;
  246.     endp = &(f->setword[NumWords(TokenNum-1)]);
  247.     esetnum++;
  248.     fprintf(DefFile, "extern unsigned zzerr%d[];\n", esetnum);
  249.     fprintf(ErrFile, "unsigned zzerr%d[%d] = {", esetnum, NumWords(TokenNum-1));
  250.     while ( p < endp )
  251.     {
  252.         if ( e > 1 ) fprintf(ErrFile, ", ");
  253.         fprintf(ErrFile, "0x%x", *p++);
  254.         if ( e == 7 )
  255.         {
  256.             if ( p < endp ) fprintf(ErrFile, ",");
  257.             fprintf(ErrFile, "\n\t");
  258.             e=1;
  259.         }
  260.         else e++;
  261.     }
  262.     fprintf(ErrFile, "};\n");
  263.  
  264.     return esetnum;
  265. }
  266.  
  267. void
  268. GenErrHdr()
  269. {
  270.     int i, j;
  271.  
  272.     fprintf(ErrFile, "/*\n");
  273.     fprintf(ErrFile, " * A n t l r  S e t s / E r r o r  F i l e  H e a d e r\n");
  274.     fprintf(ErrFile, " *\n");
  275.     fprintf(ErrFile, " * Generated from:");
  276.     for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);
  277.     fprintf(ErrFile, "\n");
  278.     fprintf(ErrFile, " *\n");
  279.     fprintf(ErrFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
  280.     fprintf(ErrFile, " * Purdue University Electrical Engineering\n");
  281.     fprintf(ErrFile, " * ANTLR Version %s\n", Version);
  282.     fprintf(ErrFile, " */\n\n");
  283.     fprintf(ErrFile, "#include <stdio.h>\n");
  284.     if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );
  285.     if ( LL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);
  286.     fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", EofToken);
  287.     fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1));
  288.     if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");
  289.     fprintf(ErrFile, "#include \"antlr.h\"\n");
  290.     fprintf(ErrFile, "#include \"dlgdef.h\"\n");
  291.     fprintf(ErrFile, "#include \"err.h\"\n\n");
  292.  
  293.     /* Dump a zztokens for each automaton */
  294.     fprintf(ErrFile, "char *zztokens[%d]={\n", TokenNum-1);
  295.     fprintf(ErrFile, "\t/* 00 */\t\"Invalid\",\n");
  296.     if ( TokenStr[EofToken] != NULL )
  297.         fprintf(ErrFile, "\t/* %02d */\t\"%s\"", EofToken, TokenStr[i]);
  298.     else
  299.         fprintf(ErrFile, "\t/* %02d */\t\"EOF\"", EofToken);
  300.     for (i=TokenStart; i<TokenNum-1; i++)
  301.     {
  302.         if ( i == EpToken ) continue;
  303.         if ( TokenStr[i] != NULL )
  304.             fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenStr[i]);
  305.         else
  306.         {
  307.             /* look in all lexclasses for the reg expr */
  308.             for (j=0; j<NumLexClasses; j++)
  309.             {
  310.                 lexmode(j);
  311.                 if ( ExprStr[i] != NULL )
  312.                 {
  313.                     fprintf(ErrFile, ",\n\t/* %02d */\t", i);
  314.                     dumpExpr(ExprStr[i]);
  315.                     break;
  316.                 }
  317.             }
  318.             require(j<NumLexClasses, eMsgd("No label or expr for token %d",i));
  319.         }
  320.     }
  321.     fprintf(ErrFile, "\n};\n");
  322. }
  323.  
  324. void
  325. dumpExpr(e)
  326. char *e;
  327. {
  328.     while ( *e!='\0' )
  329.     {
  330.         if ( *e=='\\' && *(e+1)=='\\' )
  331.             {putc('\\', ErrFile); putc('\\', ErrFile); e+=2;}
  332.         else if ( *e=='\\' && *(e+1)=='"' )
  333.             {putc('\\', ErrFile); putc('"', ErrFile); e+=2;}
  334.         else if ( *e=='\\' ) {putc('\\', ErrFile); putc('\\', ErrFile); e++;}
  335.         else {putc(*e, ErrFile); e++;}
  336.     }
  337. }
  338.  
  339.